home *** CD-ROM | disk | FTP | other *** search
- /*
- sp_pdl_print.c - print a data packet by interpreting the pdl data
- structure
- */
-
- #include "sc.h"
- #include "sc_seer_globals.h"
- #include "pdl_data.h"
-
- #include "OUT.h" /* how this to actually print strings */
-
- /* forward prototype for pdl central processor unit */
- void pr_cpu(void);
-
- static char maptoprint[17]="0123456789abcdef";
- /*
- logical and mask for bit sizes
- */
- static uint32 bit_mask[33]={
- 0,
- 0x00000001,0x00000003,0x00000007,0x0000000f,
- 0x0000001f,0x0000003f,0x0000007f,0x000000ff,
- 0x000001ff,0x000003ff,0x000007ff,0x00000fff,
- 0x00001fff,0x00003fff,0x00007fff,0x0000ffff,
- 0x0001ffff,0x0003ffff,0x0007ffff,0x000fffff,
- 0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
- 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,
- 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
- };
-
- /*
- pr_error - process a pdl error
- */
- void pr_error(err)
- char *err;
- {OUT_brk();
- OUT_str(err); /* print the error message */
- longjmp(ppg.pr_jmp_buf,1); /* quit pdl */
- }
-
- /*
- load some bits from the data stream
- */
- uint32 slurp_bits(int);
- uint32 slurp_bits(bitsize)
- register int bitsize;
- {register uint32 result;
- register int bits_here;
- result=0; /* start with no bits on in the result */
- ppg.pr_size -= bitsize; /* account for bits used from the packet */
- if(ppg.pr_size<0)
- pr_error("??packet too short");
- while(bitsize>0) { /* slurp some bits */
- bits_here=min(bitsize,ppg.pr_curb); /* how many to get from current byte */
- bitsize -= bits_here; /* account for the bits we are providing */
- result <<= bits_here; /* make room for this chunk */
- /* bits from current byte*/
- result |= (bit_mask[bits_here] & ((*ppg.pr_data)>>(ppg.pr_curb-bits_here)));
-
- /* advance data stream */
- ppg.pr_curb -= bits_here; /* get bits out of the current byte */
- if(ppg.pr_curb==0) { /* this byte empty? */
- ppg.pr_data++; /* advance data pointer */
- ppg.pr_curb=BITS_PER_DATA; /* reset bits left in this byte */
- }
- }
- return result;
- }
-
- /*
- print a number in some base
- */
- #define MAX_int_DEC (40) /* larger than largest integer as a string */
- char *pr_base(char *,uint32,int);
- char *pr_base(dec_put,val,base)
- register char *dec_put;
- register uint32 val;
- register int base;
- {register uint32 new_val;
- *--dec_put = 0; /* end the string with a null */
- do {
- new_val = val / base; /* pick out a digit */
- *--dec_put = maptoprint[val - (new_val * base)];
- val = new_val; /* remaining bits */
- } while (val!=0);
- return dec_put;
- };
- /*
- print a hex number
- */
- pr_hex(uint32);
- pr_hex(val)
- uint32 val;
- {char prstr[MAX_int_DEC+1];
- register char *astext;
- astext=pr_base(&prstr[MAX_int_DEC+1],val,16);
- *--astext = '$'; /* hex numbers begin with dollar signs */
- OUT_str(astext);
- }
-
- /*
- print a decicmal number
- */
- pr_dec(uint32);
- pr_dec(val)
- uint32 val;
- {char prstr[MAX_int_DEC+1];
- OUT_str(pr_base(&prstr[MAX_int_DEC+1],val,10));
- }
-
- /*
- print a string with a count
- */
- #define out_ch(xxx) *outpt++ = (xxx)
- #define out_ctl(xxx) {out_ch('^');out_ch(xxx);}
- pr_cnt_str(void);
- pr_cnt_str()
- {register int len;
- char buf[540]; /* worst case string size is 2*(2^8)+1 */
- register char *outpt; /* current pointer into the output buffer */
- register char ch;
- len=slurp_bits(8); /* get the string length */
- OUT_str("[");
- pr_dec(len);
- OUT_str("]");
- /* make up the string to print */
- outpt=buf; /* put characters here */
- out_ch('"');
- while((--len)>=0) { /* until the string is printed */
- ch=slurp_bits(8); /* get the next character from the input stream */
- ch &= 0x7f; /* mask out parity */
- if(ch==0x7f) /* a delete? */
- out_ctl('?') /* yes print this way */
- else if(ch<' ') /* less than a space, a control char? */
- out_ctl(((ch&0x1f)+'@')) /* yes, print as ^x */
- else if(ch=='^') /* an up arrow? */
- out_ctl('^') /* yes, double it */
- else
- out_ch(ch);
- }
- out_ch('"');
- out_ch(0); /* terminate the string */
- OUT_str(buf);
- }
-
- void pr_ip_adr(uint32);
- void pr_ip_adr(a_val)
- uint32 a_val;
- {pr_dec((a_val>>24) & 0xff); /* print a byte */
- OUT_str(".");
- pr_dec((a_val>>16) & 0xff); /* print a byte */
- OUT_str(".");
- pr_dec((a_val>>8) & 0xff); /* print a byte */
- OUT_str(".");
- pr_dec(a_val & 0xff); /* print a byte */
- }
-
- /*
- impliment the field opcode
- */
- void pr_FLD(void);
- void pr_FLD()
- {register int prf_size,temp; /* will contain size in bits of this field*/
- nd_fvalue fld_vals;
- register uint32 pr_value; /* the value of this field (if a number) */
- int print_how;
- fld_vals = *((nd_fvalue *)&ppg.pr_ip->nd_value); /* get our bits from nd_size */
-
- /* figure the field size */
- prf_size=fld_vals.nd_size; /* assume the size is a number */
- if(fld_vals.nd_indsize) /* size indirect? */
- prf_size=ppg.pr_regs[prf_size]; /* yes, load it from a register */
-
- if((temp=fld_vals.nd_indreg)!=0) { /* load value from a register? */
- pr_value=ppg.pr_regs[temp]; /* yes */
- pr_value &=bit_mask[prf_size]; /* keep only bits valid for this size */
- }
- else
- pr_value=slurp_bits(prf_size); /* get the bits from the data stream */
-
-
- /* we have the value now, if we want to save it in a register do so */
- if((temp=fld_vals.nd_lodreg)!=0) /* want to save the value? */
- ppg.pr_regs[temp]=pr_value; /* yes, do so */
-
-
- ppg.pr_last_value = pr_value; /* save for 'name' to match */
-
- print_how=fld_vals.nd_print; /* see how to print */
- if(print_how==PR_REAL(NOPRINT)) /* want to print at all? */
- return; /* no, we are done then */
-
- OUT_brk(); /* break output here */
- OUT_str(RES_str(ppg.pr_ip->nd_str)); /* say what the field is */
- OUT_str("=");
-
- /* print this field as desired */
- switch(print_how) {
- case PR_REAL(HEX):
- pr_hex(pr_value);
- break;
- case PR_REAL(DEC):
- pr_dec(pr_value);
- break;
- case PR_REAL(NOPRINT):
- break;
- case PR_REAL(CNT_STR):
- pr_cnt_str();
- break;
- case PR_REAL(IP_ADR):
- pr_ip_adr(pr_value);
- break;
- }
- }
-
- /*
- implement the name opcode
- */
- void pr_NAME(void);
- void pr_NAME()
- {if(ppg.pr_ip->nd_value!=ppg.pr_last_value) /* match last field value? */
- return; /*no, we have nothing to do then */
- /* our value matched the last 'field' value so print our name */
- OUT_str("(");
- OUT_str(RES_str(ppg.pr_ip->nd_str));
- OUT_str(")");
- }
-
- /*
- the GOSUB opcode
- */
- void pr_GOSUB(void);
- void pr_GOSUB()
- {register nd_res * save_next;
- save_next = ppg.pr_next; /* remember where to return to */
- ppg.pr_ip = RES_cod(ppg.pr_ip->nd_down); /* jump to gosub destination */
- pr_cpu(); /* run the cpu for the subroutine */
- ppg.pr_next = save_next; /* go back to where we where */
- }
-
- /*
- the INDGSUB opcode
- */
- void pr_INDGSUB(void);
- void pr_INDGSUB()
- {register nd_res *save_next,*whereto;
- save_next = ppg.pr_next; /* remember where to return to */
- whereto=(nd_res *)(ppg.pr_regs[ppg.pr_ip->nd_genreg]); /* see where to go to */
- if(whereto==0) /* no place to go if register is zero */
- return;
- ppg.pr_ip = whereto; /* jump to gosub destination */
- pr_cpu(); /* run the cpu for the subroutine */
- ppg.pr_next = save_next; /* go back to where we where */
- }
-
- /*
- the pr_ZERO opcode
- */
- void pr_ZERO(void);
- void pr_ZERO()
- {ppg.pr_regs[ppg.pr_ip->nd_genreg]=0; /* zero a register */
- }
-
- /*
- pr_LOOPE - repeat till end of packet opcode
- */
- void pr_LOOPE(void);
- void pr_LOOPE()
- {register nd_res * save_pc,*to_pc;
- save_pc = ppg.pr_ip; /* remember where to return to */
- to_pc=RES_cod(save_pc->nd_down); /* pc to execute*/
- while(ppg.pr_size>0) {
- ppg.pr_ip = to_pc; /* jump to gosub destination */
- pr_cpu(); /* run the cpu for the subroutine */
- }
- ppg.pr_next = save_pc +1; /* continue on after the gosub */
- }
-
- /*
- pr_LOOPC - repeat for a count opcode
- */
- void pr_LOOPC(void);
- void pr_LOOPC()
- {nd_res * save_pc,*to_pc;
- long count;
- count=ppg.pr_regs[ppg.pr_ip->nd_genreg]; /* get the repeat count */
-
- save_pc = ppg.pr_ip; /* remember where to return to */
- to_pc=RES_cod(save_pc->nd_down); /* pc to execute*/
- while((--count) >= 0) { /* loop the specified number of times */
- ppg.pr_ip = to_pc; /* jump to gosub destination */
- pr_cpu(); /* run the cpu for the subroutine */
- }
- ppg.pr_next = save_pc +1; /* continue on after the gosub */
- }
-
- /*
- the protocol opcode
- */
- void pr_PROTO(void);
- void pr_PROTO()
- {if(ppg.pr_ip->nd_value!=ppg.pr_last_value) /* match last field value? */
- return; /*no, we have nothing to do then */
- /* our value matched the last 'field' value so print our name */
- OUT_str("(");
- OUT_str(RES_str(ppg.pr_ip->nd_str));
- OUT_str(")");
-
- /* remember the address of our protocol handler for later */
- ppg.pr_regs[ppg.pr_ip->nd_genreg]=(uint32)RES_cod(ppg.pr_ip->nd_down);
- }
-
- /*
- the special opcode, call a user routine
- */
- void pr_SPECIAL(void);
- void pr_SPECIAL()
- {do_special(&ppg,ppg.pr_ip->nd_value);
- }
-
- /*
- pdl central processing unit.
- fetch an opcode, decode and execute it.
- */
- void pr_cpu()
- {register int opcode; /* pr opcode for current instruction */
-
- while(TRUE) {
- ppg.pr_next = ppg.pr_ip + 1; /* set new instruction counter */
- opcode=ppg.pr_ip->nd_type; /* get the instruction to execute */
- switch(opcode) {
- case IS_FLD:
- pr_FLD(); /* parse a field */
- break;
- case IS_END: /* end of the instruction list */
- return;
- break;
- case IS_NAME: /* match a name */
- pr_NAME();
- break;
- case IS_ZERO:
- pr_ZERO();
- break;
- case IS_INDGSUB:
- pr_INDGSUB();
- break;
- case IS_GOSUB:
- pr_GOSUB();
- break;
- case IS_LOOPE:
- pr_LOOPE();
- break;
- case IS_LOOPC:
- pr_LOOPC();
- break;
- case IS_PROTO:
- pr_PROTO();
- break;
- case IS_EOF:
- if(ppg.pr_size!=0)
- pr_error("??excess data");
- break;
- case IS_SPECIAL:
- pr_SPECIAL();
- break;
- } /* end switch on opcode */
- ppg.pr_ip = ppg.pr_next;
- } /* end while true */
- }
-
- /* print the rest in hex and ascii*/
- void hex_rest(void);
- void hex_rest()
- {/*if have a partial byte left */
- if(ppg.pr_curb!=BITS_PER_DATA) {
- OUT_brk(); /* break output here */
- OUT_str("partial byte(");
- pr_hex(BITS_PER_DATA-ppg.pr_curb);
- OUT_str(")=");
- pr_hex(slurp_bits(ppg.pr_curb));
- }
- }
-
-
- void pdl_print(packet,pdl_start,pdl_siz)
- DATA_IS *packet; /* the raw data to print */
- int pdl_start; /* how to print it */
- uint16 pdl_siz; /* how big the data is (in bits) */
- {ppg.pr_ip=RES_cod(PDL_WORLD->starts[pdl_start]); /* start reading instructions here */
- ppg.pr_size=pdl_siz; /* how many bits of data there are */
- ppg.pr_size *= 8;
- ppg.pr_data=packet; /* where to read data from */
- ppg.pr_curb=BITS_PER_DATA; /* bits left in this data byte */
-
- if(setjmp(ppg.pr_jmp_buf)!=0) /* set a place to throw errors */
- return; /* return from an error */
-
- pr_cpu(); /* run the cpu to process data */
-
- if(ppg.pr_size>0) /* have left over bits at end of packet? */
- hex_rest(); /* print the rest in hex and ascii*/
- }
-